package com.bby.screentool.manager;

import android.content.Context;
import android.widget.Toast;

import com.bby.screentool.base.Config;
import com.bby.screentool.base.RuntimeEnv;
import com.bby.screentool.exception.ServiceException;

import org.webrtc.AudioSource;
import org.webrtc.AudioTrack;
import org.webrtc.DataChannel;
import org.webrtc.DefaultVideoDecoderFactory;
import org.webrtc.DefaultVideoEncoderFactory;
import org.webrtc.EglBase;
import org.webrtc.IceCandidate;
import org.webrtc.MediaConstraints;
import org.webrtc.MediaStream;
import org.webrtc.PeerConnection;
import org.webrtc.PeerConnectionFactory;
import org.webrtc.RtpReceiver;
import org.webrtc.ScreenCapturerAndroid;
import org.webrtc.SurfaceTextureHelper;
import org.webrtc.VideoSource;
import org.webrtc.VideoTrack;

import java.util.ArrayList;
import java.util.List;

public class WebRtcResourceManager {
    //    googEchoCancellation   回音消除
    private static final String AUDIO_ECHO_CANCELLATION_CONSTRAINT = "googEchoCancellation";
    //    googNoiseSuppression   噪声抑制
    private static final String AUDIO_NOISE_SUPPRESSION_CONSTRAINT = "googNoiseSuppression";
    //    googAutoGainControl    自动增益控制
    private static final String AUDIO_AUTO_GAIN_CONTROL_CONSTRAINT = "googAutoGainControl";
    //    googHighpassFilter     高通滤波器
    private static final String AUDIO_HIGH_PASS_FILTER_CONSTRAINT = "googHighpassFilter";
    private PeerConnectionFactory factory;
    // 单例对象
    private static WebRtcResourceManager instance;
    public static final EglBase eglBase = EglBase.create();
    private PeerConnection.RTCConfiguration configuration;
    private PeerConnection peerConnection;
    private ScreenCapturerAndroid screenCapturerAndroid;
    private SurfaceTextureHelper surfaceTextureHelper;
    private WebRtcObserver observer;
    private VideoSource videoSource;
    private VideoTrack videoTrack;
    private AudioTrack audioTrack;
    private AudioSource audioSource;

    public static WebRtcResourceManager getInstance() {
        if (instance == null) {
            instance = new WebRtcResourceManager();
        }
        return instance;
    }

    public void init(Context context, WebRtcObserver observer) {
        if (this.observer == observer) {
            return;
        }
        this.observer = observer;
        init(context);
    }

    private void init(Context context) {
        //Initialising PeerConnectionFactory
        PeerConnectionFactory.InitializationOptions initializationOptions = PeerConnectionFactory.InitializationOptions.builder(context)
                .setEnableInternalTracer(true)
                .setFieldTrials("WebRTC-H264HighProfile/Enabled/")
                .createInitializationOptions();
        PeerConnectionFactory.initialize(initializationOptions);
        //创建EglBase对象
        PeerConnectionFactory.Options options = new PeerConnectionFactory.Options();
        options.disableEncryption = true;
        options.disableNetworkMonitor = true;
        factory = PeerConnectionFactory.builder()
                .setVideoDecoderFactory(new DefaultVideoDecoderFactory(eglBase.getEglBaseContext()))
                .setVideoEncoderFactory(new DefaultVideoEncoderFactory(eglBase.getEglBaseContext(), true, true))
                .setOptions(options)
                .createPeerConnectionFactory();
        // 配置STUN穿透服务器  转发服务器

        List<PeerConnection.IceServer> iceServers = new ArrayList<>();//
        iceServers.add(
                PeerConnection.IceServer
                        .builder(Config.STUN).createIceServer());
//        iceServers.add(
//                PeerConnection.IceServer
//                        .builder(Config.STUN1)
//                        .setPassword("wby12332112")
//                        .createIceServer());
//                        .setHostname("bby")
        configuration = new PeerConnection.RTCConfiguration(iceServers);
    }


    public PeerConnectionFactory getFactory() {
        return factory;
    }

    public EglBase getEglBase() {
        return eglBase;
    }

    public VideoTrack getVideoTrack() {
        return videoTrack;
    }

    public AudioTrack getAudioTrack() {
        return audioTrack;
    }

    public void releaseResource() {
        if (peerConnection != null) {
            // 关闭并释放连接
            peerConnection.dispose();
            peerConnection = null;
        }
        if (audioSource != null) {
            // 释放音频源
            audioSource.dispose();
            audioSource = null;
        }
        if (audioTrack != null) {
            audioTrack.dispose();
            audioTrack = null;
        }
        if (screenCapturerAndroid != null) {
            if (screenCapturerAndroid.isScreencast()){
                screenCapturerAndroid.stopCapture();
            }
            screenCapturerAndroid.dispose();
            screenCapturerAndroid = null;
        }
        if (videoSource != null) {
            // VideoTrack#removeSink(VideoSink sink) 外层实现
            videoSource.dispose();
            videoSource = null;
        }
        if (videoTrack != null) {
            videoTrack.dispose();
            videoTrack = null;
        }
        surfaceTextureHelper.dispose();
    }

    /**
     * 设置音频源参数
     */
    public AudioTrack createAudio(PeerConnection peerConnection) {
        MediaConstraints audioConstraints = new MediaConstraints();
        audioConstraints.mandatory.add(new MediaConstraints.KeyValuePair(AUDIO_ECHO_CANCELLATION_CONSTRAINT
                , "true"));

        audioConstraints.mandatory.add(
                new MediaConstraints.KeyValuePair(AUDIO_NOISE_SUPPRESSION_CONSTRAINT, "true"));
        audioConstraints.mandatory.add(
                new MediaConstraints.KeyValuePair(AUDIO_AUTO_GAIN_CONTROL_CONSTRAINT, "false"));
        audioConstraints.mandatory.add(
                new MediaConstraints.KeyValuePair(AUDIO_HIGH_PASS_FILTER_CONSTRAINT, "true"));
        audioSource = factory.createAudioSource(audioConstraints);
        // 音频轨
        audioTrack = factory.createAudioTrack("ARDAMSa0", audioSource);
        peerConnection.addTrack(audioTrack);
        return audioTrack;
    }

    public VideoTrack createResources(Context context, ScreenCapturerAndroid screenCapturerAndroid){
        this.screenCapturerAndroid = screenCapturerAndroid;
        surfaceTextureHelper = SurfaceTextureHelper.create(Thread.currentThread().getName(), eglBase.getEglBaseContext());
        videoSource = factory.createVideoSource(screenCapturerAndroid.isScreencast());
        screenCapturerAndroid.initialize(surfaceTextureHelper, context, videoSource.getCapturerObserver());
        screenCapturerAndroid.startCapture(RuntimeEnv.RECORD_WIDTH, RuntimeEnv.RECORD_HEIGHT, Config.VIDEO_FPS);
        Toast.makeText(context, "Start recording", Toast.LENGTH_SHORT).show();
        videoTrack = factory.createVideoTrack("videtrack", videoSource);
        createAudio(peerConnection);
        return videoTrack;
    }

    public PeerConnection createPeerConnection() throws ServiceException {
        if (peerConnection == null || peerConnection.connectionState() == PeerConnection.PeerConnectionState.CLOSED) {
            if (peerConnection != null) {
                peerConnection.dispose();
            }
            peerConnection = factory.createPeerConnection(configuration, new PeerConnectionObserver(observer));
            if (peerConnection == null) {
                throw new ServiceException("创建 peerConnection 失败！");
            }
        }
        return peerConnection;
    }

    private static class PeerConnectionObserver implements PeerConnection.Observer {
        WebRtcObserver observer;

        public PeerConnectionObserver(WebRtcObserver observer) {
            this.observer = observer;
        }

        @Override
        public void onIceCandidate(IceCandidate iceCandidate) {
            observer.onIceCandidate(iceCandidate);
        }

        @Override
        public void onAddStream(MediaStream mediaStream) {
            observer.onAddStream(mediaStream);

        }

        @Override
        public void onIceConnectionChange(PeerConnection.IceConnectionState iceConnectionState) {
            observer.onIceConnectionChange(iceConnectionState);
        }

        @Override
        public void onIceConnectionReceivingChange(boolean b) {
        }

        @Override
        public void onSignalingChange(PeerConnection.SignalingState signalingState) {

        }

        @Override
        public void onIceGatheringChange(PeerConnection.IceGatheringState iceGatheringState) {

        }

        @Override
        public void onIceCandidatesRemoved(IceCandidate[] iceCandidates) {

        }


        @Override
        public void onRemoveStream(MediaStream mediaStream) {

        }

        @Override
        public void onDataChannel(DataChannel dataChannel) {

        }

        @Override
        public void onRenegotiationNeeded() {

        }

        @Override
        public void onAddTrack(RtpReceiver rtpReceiver, MediaStream[] mediaStreams) {

        }
    }

    public interface WebRtcObserver {
        void onIceCandidate(IceCandidate iceCandidate);

        void onAddStream(MediaStream mediaStream);

        void onIceConnectionChange(PeerConnection.IceConnectionState iceConnectionState);
    }
}
